#include <stdio.h>

#include <sys/types.h>
#include <string.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>

#include <signal.h>
#include <string.h>
#include <stdbool.h>
#include <errno.h>

#include "media_ipc_msg.h"
#include "debug/debug.h"
#include "media.h"
#include "media_message.h"

tsPortDataCtrl g_PortDataCtrl;
static bool eventloop_quit = false;

//-------------------------------------------------------------------------------
int dispose_mode_scale(void* data, int size);
int dispose_video_rotater(void* data, int size);
int dispose_video_photo(void* data, int size);
int dispose_video_record(void* data, int size);
int dispose_video_replay(void* data, int size);
int dispose_get_file_proc(void* data, int size);
int dispose_mode_switch(void* data, int size);
int dispose_set_whiteblack(void* data, int size);
int dispose_video_mirror(void* data, int size);
int dispose_set_ab_play(void* data, int size);
//-------------------------------------------------------------------------------
const uint8_t nCrc8Tab[] =
{
	0x00, 0x5e, 0xbc, 0xe2, 0x61, 0x3f, 0xdd, 0x83, 0xc2, 0x9c, 0x7e, 0x20, 0xa3, 0xfd, 0x1f, 0x41,
	0x9d, 0xc3, 0x21, 0x7f, 0xfc, 0xa2, 0x40, 0x1e, 0x5f, 0x01, 0xe3, 0xbd, 0x3e, 0x60, 0x82, 0xdc,
	0x23, 0x7d, 0x9f, 0xc1, 0x42, 0x1c, 0xfe, 0xa0, 0xe1, 0xbf, 0x5d, 0x03, 0x80, 0xde, 0x3c, 0x62,
	0xbe, 0xe0, 0x02, 0x5c, 0xdf, 0x81, 0x63, 0x3d, 0x7c, 0x22, 0xc0, 0x9e, 0x1d, 0x43, 0xa1, 0xff,
	0x46, 0x18, 0xfa, 0xa4, 0x27, 0x79, 0x9b, 0xc5, 0x84, 0xda, 0x38, 0x66, 0xe5, 0xbb, 0x59, 0x07,
	0xdb, 0x85, 0x67, 0x39, 0xba, 0xe4, 0x06, 0x58, 0x19, 0x47, 0xa5, 0xfb, 0x78, 0x26, 0xc4, 0x9a,
	0x65, 0x3b, 0xd9, 0x87, 0x04, 0x5a, 0xb8, 0xe6, 0xa7, 0xf9, 0x1b, 0x45, 0xc6, 0x98, 0x7a, 0x24,
	0xf8, 0xa6, 0x44, 0x1a, 0x99, 0xc7, 0x25, 0x7b, 0x3a, 0x64, 0x86, 0xd8, 0x5b, 0x05, 0xe7, 0xb9,
	0x8c, 0xd2, 0x30, 0x6e, 0xed, 0xb3, 0x51, 0x0f, 0x4e, 0x10, 0xf2, 0xac, 0x2f, 0x71, 0x93, 0xcd,
	0x11, 0x4f, 0xad, 0xf3, 0x70, 0x2e, 0xcc, 0x92, 0xd3, 0x8d, 0x6f, 0x31, 0xb2, 0xec, 0x0e, 0x50,
	0xaf, 0xf1, 0x13, 0x4d, 0xce, 0x90, 0x72, 0x2c, 0x6d, 0x33, 0xd1, 0x8f, 0x0c, 0x52, 0xb0, 0xee,
	0x32, 0x6c, 0x8e, 0xd0, 0x53, 0x0d, 0xef, 0xb1, 0xf0, 0xae, 0x4c, 0x12, 0x91, 0xcf, 0x2d, 0x73,
	0xca, 0x94, 0x76, 0x28, 0xab, 0xf5, 0x17, 0x49, 0x08, 0x56, 0xb4, 0xea, 0x69, 0x37, 0xd5, 0x8b,
	0x57, 0x09, 0xeb, 0xb5, 0x36, 0x68, 0x8a, 0xd4, 0x95, 0xcb, 0x29, 0x77, 0xf4, 0xaa, 0x48, 0x16,
	0xe9, 0xb7, 0x55, 0x0b, 0x88, 0xd6, 0x34, 0x6a, 0x2b, 0x75, 0x97, 0xc9, 0x4a, 0x14, 0xf6, 0xa8,
	0x74, 0x2a, 0xc8, 0x96, 0x15, 0x4b, 0xa9, 0xf7, 0xb6, 0xe8, 0x0a, 0x54, 0xd7, 0x89, 0x6b, 0x35,
};

//-------------------------------------------------------------------------------
int send_ipc_msg(char* pdata, int size);

//-------------------------------------------------------------------------------
uint8_t CalCrc8(uint8_t *pBuf, uint8_t nBufLen)
{
	uint8_t  nCrcVal = 0;
	uint8_t  i = 0;
	uint8_t  nTabIdx = 0;

	if (pBuf && (nBufLen > 0))
	{
		for (i = 0; i < nBufLen; i++)
		{
			nTabIdx = (*(pBuf + i)) ^ nCrcVal;
			nCrcVal = nCrc8Tab[nTabIdx];
		}
	}

	return nCrcVal;
}

//--------------------------------------------------------------------------
static tsIdAddr id_addr[] = {
	{ ID_UI, {AF_UNIX, "/tmp/ui_socket"} },
	{ ID_IMAGE, {AF_UNIX, "/tmp/image_socket"} },
};

static int id_addr_len = sizeof(id_addr) / sizeof(id_addr[0]);
int sockfd = 0;

//--------------------------------------------------------------------------
struct media_cmd_oper cmd_oper[] = {
	/* 模式切换 */
	[MEDIA_CMD_MODE_SWITCH] = {
		.cmd_str = "MEDIA_CMD_MODE_SWITCH",
		.oper = dispose_mode_switch,
	},

	/* 图像缩放 */
	[MEDIA_CMD_VIDEO_SCALE] = {
		.cmd_str = "MEDIA_CMD_VIDEO_SCALE",
		.oper = dispose_mode_scale,
	},

	/* 图像旋转 */
	[MEDIA_CMD_AUTOUP] = {
		.cmd_str = "MEDIA_CMD_AUTOUP",
		.oper = dispose_video_rotater,
	},

	[MEDIA_CMD_MIRROR] = {
		.cmd_str = "MEDIA_CMD_MIRROR",
		.oper = dispose_video_mirror,
	},
	
	/* 拍照 */
	[MEDIA_CMD_PHOTO] = {
		.cmd_str = "MEDIA_CMD_PHOTO",
		.oper = dispose_video_photo,
	},

	/* 录像 */
	[MEDIA_CMD_RECORD_START] = {
		.cmd_str = "MEDIA_CMD_RECORD_START",
		.oper = dispose_video_record,
	},

	[MEDIA_CMD_RECORD_STOP] = {
	.cmd_str = "MEDIA_CMD_RECORD_STOP",
	.oper = dispose_video_record,
	},

	/* 回放/暂停 */
	[MEDIA_CMD_REPLAY] = {
		.cmd_str = "MEDIA_CMD_REPLAY",
		.oper = dispose_video_replay,
	},

	/* 获取媒体信息，如avi文件时长 */
	[MEDIA_CMD_MEDIA_PROC] = {
		.cmd_str = "MEDIA_CMD_MEDIA_PROC",
		.oper = dispose_get_file_proc,
	},
	[MEDIA_CMD_WHITEBLACK] = {
		.cmd_str = "MEDIA_CMD_WHITEBLACK",
		.oper = dispose_set_whiteblack,
	},
	[MEDIA_CMD_AB_PLAY] = {
		.cmd_str = "MEDIA_CMD_AB_PLAY",
		.oper = dispose_set_ab_play,
	},

};

//--------------------------------------------------------------------------
struct sockaddr_un * find_sun_addr(int id)
{
	struct sockaddr_un *psun = NULL;

	for (int i = 0; i < id_addr_len; i++)
	{
		if (id_addr[i].id == id)
			psun = &id_addr[i].sun_addr;
	}

	return psun;
}

int ack_camera(int state)
{
	uint8_t data[20];
	int pos = 0;

	data[pos++] = MEDIA_CMD_CAMERA_STATE;
	data[pos++] = 0x00;
	data[pos++] = 0x01;
	data[pos++] = (state == WT_SUCCESS ? WT_SUCCESS : WT_ERR_COMM_OPER);

	return send_ipc_msg(data, pos);
}


//--------------------------------------------------------------------------
uint8_t FillTxFrame(uint8_t addr, uint8_t cmd, uint8_t *pdata, int len, uint8_t *out)
{
	uint8_t pos = 0, cs = 0;

	out[pos++] = 0x55;
	out[pos++] = 0xaa;
	out[pos++] = 7 + len;
	out[pos++] = cmd;
	out[pos++] = CalCrc8(out, 4);
	out[pos++] = addr;
	memcpy(&out[pos], pdata, len);
	pos += len;
	cs = CalCrc8(out, pos);
	out[pos++] = cs;

	return pos;
}

//--------------------------------------------------------------------------
uint8_t FillRxFrame(uint8_t addr, uint8_t *pdata, int len, uint8_t *out)
{
	int pos = 0;

	out[pos++] = 0x5a;
	out[pos++] = 0xa5;
	out[pos++] = 6 + len + 1;
	out[pos++] = 0x33;
	out[pos++] = CalCrc8(out, 4);
	out[pos++] = addr;
	memcpy(&out[pos], pdata, len);
	pos += len;
	out[pos] = CalCrc8(out, pos);
	pos ++;

	return pos;
}

//--------------------------------------------------------------------------
uint32_t protocal_check_comm(uint8_t *pdata, int16_t len)
{
	uint32_t ret = WT_SUCCESS;
	int16_t dlen;
	uint8_t crc, crc_tmp;

	if (pdata[0] != 0x55 || pdata[1] != 0xaa)
	{
		ret = WT_ERR_COMM_HEADER;
		goto ERR_EXIT;
	}

	dlen = pdata[2];
	if (dlen > len)
	{
		ret = WT_ERR_COMM_LENGTH;
		goto ERR_EXIT;
	}

	if (pdata[3] != 0x22 && pdata[3] != 0x33)
	{
		ret = WT_ERR_COMM_DATA;
		goto ERR_EXIT;
	}

	crc_tmp = pdata[4];
	crc = CalCrc8(pdata, 4);
	if (crc != crc_tmp)
	{
		ret = WT_ERR_COMM_CRC;
		goto ERR_EXIT;
	}

	crc_tmp = pdata[dlen - 1];
	crc = CalCrc8(pdata, dlen - 1);
	if (crc != crc_tmp)
	{
		ret = WT_ERR_COMM_CRC;
		goto ERR_EXIT;
	}

ERR_EXIT:
	return ret;
}

//--------------------------------------------------------------------------
bool CheckFrame(uint8_t *rx_data, int rx_len, uint8_t **pRet)
{
	int dlen = 0;
	uint8_t *pdata = rx_data;
	uint8_t *ptmp = rx_data;
	int len = rx_len;
	bool bret = false;

	while (len >= 8)
	{
		if (pdata[0] == 0x55 && pdata[1] == 0xaa)
		{
			dlen = pdata[2];

			if (protocal_check_comm(pdata, len) == WT_SUCCESS)
			{
				memcpy(g_PortDataCtrl.cmd_data[g_PortDataCtrl.cmd_idx], pdata, dlen);
				g_PortDataCtrl.cmd_len[g_PortDataCtrl.cmd_idx] = dlen;

				len -= dlen;
				pdata += dlen;

				ptmp = pdata;
				bret = true;

				g_PortDataCtrl.cmd_idx += 1;
				if (g_PortDataCtrl.cmd_idx >= MAX_CMD_BUF_CNT)
					break;
			}
			else
			{
				len--;
				pdata++;
			}
		}
		else
		{
			len--;
			pdata++;
		}
	}

	*pRet = ptmp;

	return bret;
}

//-------------------------MEDIA_CMD_MODE_SWITCH-------------------------------------------------
//uint8_t	0:实时图像(video)，1:历史回看(review)
int dispose_mode_switch(void* data, int size)
{
	uint8_t* p_data = data;
	int ret = -1;

	if (size == 1)
	{
		if (p_data[0] == 0)
		{
			print_debug("switch to Image Video mode.");
			media_reader_stop();
			ret = media_previewer_start();
		}
		else if (p_data[0] == 1)
		{
			print_debug("switch to Image Review mode.");
			media_previewer_stop();
			ret = media_reader_start();
			
		}

		if (ret == 0)
			ret = WT_SUCCESS;
		else
			ret = WT_ERR_COMM_OPER;
	}
	else
		ret = WT_ERR_COMM_DLEN;

	return ret;
}

//------------------------MEDIA_CMD_VIDEO_SCALE--------------------------------------------------
//uint8_t 0:原始，1:2x，2 : 3x，3：4x
int dispose_mode_scale(void* data, int size)
{
	int ret = -1;
	uint8_t* p_data = data;

	g_PortDataCtrl.tx_len = 0;

	if (size != 1)
		return WT_ERR_COMM_DLEN;

	if (p_data[0] >= MAX_VIDEO_SCALE_UP_STEP)
		return WT_ERR_COMM_DATA;

	if (get_media_mode().mode_state.state.media_preview_start == false)
		return WT_ERR_COMM_OPER;

	print_debug("video scale %d.", p_data[0]);
	ret = media_send_action_cmd(VIDEO_ACTION_SCALE, VIDEO_ACTION_CMD_NONE, p_data, size);
	if (ret < 0)
		return WT_ERR_COMM_OPER;

	return WT_DELAY_ACK;

}

int ack_video_scale(int state)
{
	uint8_t data[20];
	int pos = 0;

	data[pos++] = MEDIA_CMD_VIDEO_SCALE;
	data[pos++] = 0x00;
	data[pos++] = 0x01;
	data[pos++] = (state == WT_SUCCESS ? WT_SUCCESS : WT_ERR_COMM_OPER);

	return send_ipc_msg(data, pos);
}

int dispose_video_mirror(void* data, int size)
{
	int ret = -1;
	uint8_t* p_data = data;

	if (size != 1)
		return WT_ERR_COMM_DLEN;

	ret = media_send_action_cmd(VIDEO_ACTION_MIRROR, VIDEO_ACTION_CMD_NONE, p_data, size);
	if (ret < 0)
		return WT_ERR_COMM_OPER;

	return WT_DELAY_ACK;
}

int ack_video_mirror(int state)
{
	uint8_t data[20];
	int pos = 0;

	data[pos++] = VIDEO_ACTION_MIRROR;
	data[pos++] = 0x00;
	data[pos++] = 0x01;
	data[pos++] = (state == WT_SUCCESS ? WT_SUCCESS : WT_ERR_COMM_OPER);

	return send_ipc_msg(data, pos);
}

//------------------------MEDIA_CMD_ROTATER--------------------------------------------------
//0：原始，1：90度，2：180度，3：270度
int dispose_video_rotater(void* data, int size)
{
	int ret = -1;
	uint8_t* p_data = data;

	if (size != 1)
		return WT_ERR_COMM_DLEN;

	if (p_data[0] >= 360)
		return WT_ERR_COMM_DATA;

	print_debug("video rotater %d.", p_data[0]);
	ret = media_send_action_cmd(VIDEO_ACTION_ROTATER, VIDEO_ACTION_CMD_NONE, p_data, size);
	if (ret < 0)
		return WT_ERR_COMM_OPER;

	return WT_DELAY_ACK;

}

int ack_video_rotater(int state)
{
	uint8_t data[20];
	int pos = 0;

	data[pos++] = MEDIA_CMD_AUTOUP;
	data[pos++] = 0x00;
	data[pos++] = 0x01;
	data[pos++] = (state == WT_SUCCESS ? WT_SUCCESS : WT_ERR_COMM_OPER);

	return send_ipc_msg(data, pos);
}

//------------------------MEDIA_CMD_PHOTO--------------------------------------------------
// 文件名
int dispose_video_photo(void* data, int size)
{
	int ret;
	uint8_t *p_data = data;

	p_data[size] = 0;

	if (get_media_mode().mode_state.state.media_preview_start == false)
		return WT_ERR_COMM_OPER;

	if (size > MAX_RECORD_FILE_NAME_LENGHT || size == 0 || strlen(data) != size)
		return WT_ERR_COMM_DLEN;
	print_debug("video photo file:%s", p_data);
	ret = media_send_action_cmd(VIDEO_ACTION_PHOTO, VIDEO_ACTION_CMD_START, p_data, size);
	if (ret < 0)
		return WT_ERR_COMM_OPER;

	return WT_DELAY_ACK;
}
//
int ack_video_photo(int state)
{
	uint8_t data[20];
	int pos = 0;
	
	data[pos++] = MEDIA_CMD_PHOTO;
	data[pos++] = 0x00;
	data[pos++] = 0x01;
	data[pos++] = (state == WT_SUCCESS ? WT_SUCCESS : WT_ERR_COMM_OPER);

	return send_ipc_msg(data, pos);
}

//------------------------MEDIA_CMD_RECORD--------------------------------------------------
// 0:停止，1：录像+文件名
int dispose_video_record(void* data, int size)
{
	int ret = -1;
	uint8_t* p_data = data;
	struct video_cmd* cmd = NULL;

	p_data[size] = 0;
	print_function_entry();

	if (get_media_mode().mode_state.state.media_preview_start == false)
		return WT_ERR_COMM_OPER;

	//停止录像
	if (size == 1 && p_data[0] == 0)
	{
		print_debug("video record stop" );
		ret = media_send_action_cmd(VIDEO_ACTION_RECORD, VIDEO_ACTION_CMD_STOP, p_data, 0);

		if (ret < 0)
			return WT_ERR_COMM_OPER;

		return WT_DELAY_ACK;

	}else if (size > (MAX_RECORD_FILE_NAME_LENGHT + 1) || size == 0 || strlen(p_data) != size)
		return WT_ERR_COMM_DLEN;

	if (p_data[0] == 1)
	{
		//正在录像
		if (get_record_video_state() == true)
			return WT_ERR_COMM_OPER;

		//开始录像
		print_debug("video record start filename:%s.", p_data + 1);
		ret = media_send_action_cmd(VIDEO_ACTION_RECORD, VIDEO_ACTION_CMD_START, p_data + 1, size - 1);
		if (ret < 0)
			return WT_ERR_COMM_OPER;

		return WT_DELAY_ACK;
	}
	return WT_ERR_COMM_DATA;
}

int ack_video_record(enum media_cmd_type cmd, int state)
{
	uint8_t data[20];
	int pos = 0;
	
	print_debug("ack_video_record" );

	data[pos++] = cmd;
	data[pos++] = 0x00;
	data[pos++] = 0x01;
	data[pos++] = (state == WT_SUCCESS ? WT_SUCCESS : WT_ERR_COMM_OPER);

	return send_ipc_msg(data, pos);
}

//------------------------MEDIA_CMD_REPLAY--------------------------------------------------
int dispose_video_replay(void* data, int size)
{
	int ret = -1;
	uint8_t* p_data = data;
	enum media_replay_type replay_type = (enum media_replay_type) p_data[0];

	if (size != 1)
		return WT_ERR_COMM_DLEN;

	if (get_media_mode().mode_state.state.media_play_start == false)
		return WT_ERR_COMM_OPER;

	if (replay_type == MEDIA_REPLAY_STOP)
	{
		print_debug("stop video replay.");
		ret = media_send_action_cmd(VIDEO_ACTION_PLAY, VIDEO_ACTION_CMD_STOP, NULL, 0);
	}
	else if (replay_type == MEDIA_REPLAY_PAUSE)
	{
		print_debug("start video pause.");
		ret = media_send_action_cmd(VIDEO_ACTION_PLAY, VIDEO_ACTION_CMD_PAUSE, NULL, 0);
	}
	else if (replay_type == MEDIA_REPLAY_START)
	{
		print_debug("start video replay.");
		ret = media_send_action_cmd(VIDEO_ACTION_PLAY, VIDEO_ACTION_CMD_START, NULL, 0);
	}

	if (ret < 0)
	{
		return WT_ERR_COMM_OPER;
	}

	return ret ;
}

int ack_video_repaly(int state, enum media_replay_type replay_type)
{
	uint8_t data[20];
	int pos = 0;

	data[pos++] = MEDIA_CMD_REPLAY;
	data[pos++] = 0x00;
	data[pos++] = 0x02;
	data[pos++] = replay_type;
	data[pos++] = (state == WT_SUCCESS ? WT_SUCCESS : WT_ERR_COMM_OPER);

	return send_ipc_msg(data, pos);
}

int dispose_set_ab_play(void* data, int size)
{
	int ret = -1;
	uint8_t *p_data = (uint8_t *)data;
	
	if (get_media_mode().mode_state.state.media_play_start == false)
		return WT_ERR_COMM_OPER;

	if( size >= 4 )
	{
		ret = media_send_action_cmd(VIDEO_ACTION_PLAY, VIDEO_ACTION_CMD_AB_PLAY, p_data, size);
		if (ret < 0)
		{
			return WT_ERR_COMM_OPER;
		}
	}

	return WT_DELAY_ACK;

}

int ack_video_ab_play(int state)
{
	uint8_t data[20];
	int pos = 0;

	data[pos++] = MEDIA_CMD_AB_PLAY;
	data[pos++] = 0x00;
	data[pos++] = 0x01;
	data[pos++] = (state == WT_SUCCESS ? WT_SUCCESS : WT_ERR_COMM_OPER);

	return send_ipc_msg(data, pos);
}


int dispose_set_whiteblack(void* data, int size)
{
	int ret = -1;
	uint8_t *p_data = (uint8_t *)data;

	p_data[size] = 0;
	print_debug("set whiteblack: %s", p_data);
	ret = media_send_action_cmd(VIDEO_ACTION_WHITEBLACK, VIDEO_ACTION_CMD_NONE, p_data, size);
	if (ret < 0)
	{
		return WT_ERR_COMM_OPER;
	}

	return WT_DELAY_ACK;

}

int ack_video_whiteblack(int state)
{
	uint8_t data[20];
	int pos = 0;

	data[pos++] = MEDIA_CMD_WHITEBLACK;
	data[pos++] = 0x00;
	data[pos++] = 0x01;
	data[pos++] = (state == WT_SUCCESS ? WT_SUCCESS : WT_ERR_COMM_OPER);

	return send_ipc_msg(data, pos);
}

//------------------------MEDIA_CMD_MEDIA_PROC--------------------------------------------------
int dispose_get_file_proc(void* data, int size)
{
	int ret = -1;
	uint8_t* p_data = data;

	p_data[size] = 0;
	print_debug("select file: %s", p_data);

	if (get_media_mode().mode_state.state.media_play_start == false)
		return WT_ERR_COMM_OPER;

	ret = media_send_action_cmd(VIDEO_ACTION_PLAY, VIDEO_ACTION_SELECT_FILE, p_data, size);
	if (ret < 0)
	{
		return WT_ERR_COMM_OPER;
	}

	return WT_DELAY_ACK;
}

int ack_get_file_proc(int state, uint8_t *file_proc, int size)
{
	uint8_t data[20];
	int pos = 0;

	data[pos++] = MEDIA_CMD_MEDIA_PROC;
	data[pos++] = 0x30;
	if (state < 0)
	{
		data[pos++] = 1;
		data[pos++] = WT_ERR_COMM_OPER;
	}
	else
	{
		data[pos++] = size;
		memcpy(&data[pos], file_proc, size);
		pos += size;
	}
	return send_ipc_msg(data, pos);
}

//-----------------------------MEDIA_ACK_REPLAY_DURATION---------------------------------------------
int ack_record_duration(uint16_t duration_sec)
{
	uint8_t data[20];
	int pos = 0;

	data[pos++] = MEDIA_ACK_RECORD_DURATION;
	data[pos++] = 0x20;
	data[pos++] = sizeof(duration_sec);

	memcpy(&data[pos], &duration_sec, sizeof(duration_sec));
	pos += sizeof(duration_sec);

	return send_ipc_msg(data, pos);
}

int ack_replay_duration(uint16_t duration_sec)
{
	uint8_t data[20];
	int pos = 0;

	data[pos++] = MEDIA_ACK_REPLAY_DURATION;
	data[pos++] = 0x20;
	data[pos++] = sizeof(duration_sec);

	memcpy(&data[pos], &duration_sec, sizeof(duration_sec));
	pos += sizeof(duration_sec);

	return send_ipc_msg(data, pos);
}

//--------------------------------------------------------------------------
void ParseCommWrite(uint8_t *papp, uint8_t dlen)
{
	uint8_t index = papp[0];
	uint8_t length = papp[2];

	uint8_t data[128];
	int pos = 0;

	int ret = -1;


	data[pos++] = index;
	data[pos++] = 0x00;

	if (cmd_oper[index].oper != NULL && length > 0)
	{
		print_function_entry();
		ret = cmd_oper[index].oper(papp + 3, length);
		if (ret != WT_DELAY_ACK)
		{
			if (ret != 0)
			{
				print_warning("%s operation failed data[0]:%#x size:%d.", cmd_oper[index].cmd_str, papp[3], length);
			}
			data[pos++] = ret;
			g_PortDataCtrl.tx_len = FillRxFrame(ID_UI, data, pos, g_PortDataCtrl.tx_data);
		}
	}
	else
	{
		print_error("unknow cmd index:%d.", index);
	}

}

//--------------------------------------------------------------------------
void ParseCommFrame(uint8_t *pdata, int len)
{
	if (protocal_check_comm(pdata, len) == WT_SUCCESS)
	{
		uint8_t len = pdata[2];
		uint8_t cmd = pdata[3];
		uint8_t id = pdata[5];
		uint8_t dlen = len - 7;
		uint8_t *papp = &pdata[6];
		struct sockaddr_un *psum = find_sun_addr(id);

		if (psum)
		{
			g_PortDataCtrl.tx_len = 0;

			switch (cmd)
			{
			case CMD_READ:
				//ParseCommRead(papp, dlen);
				break;
			case CMD_WRITE:
				ParseCommWrite(papp, dlen);
				break;
			default:				
				break;
			}

			if (g_PortDataCtrl.tx_len > 0)
			{
				len = sendto(sockfd, g_PortDataCtrl.tx_data, g_PortDataCtrl.tx_len, 0, (struct sockaddr *)psum, sizeof(*psum));
			}
		}		
	}
}

int send_ipc_msg(char* pdata, int size)
{
	int len = 0;
	uint8_t data[128];
	struct sockaddr_un* psum = find_sun_addr(ID_UI);

	len = FillRxFrame(ID_UI, pdata, size, data);
	if (psum)
	{
		 len = sendto(sockfd, data, len, 0, (struct sockaddr*)psum, sizeof(*psum));
		// printf("Image socket->Send ret %d: ", len);
		for (int i = 0; i < len; i++)
		printf("%02x ", data[i]);
		printf("\n");
	}

	return len;

}

void media_cmd_eventloop_quit(void)
{
	eventloop_quit = false;
}

//--------------------------------------------------------------------------
int media_cmd_eventloop(int msec)
{	
	int maxfd = 0;
	fd_set rset;
	struct timeval timeout;
	struct sockaddr_un *psun_ui, *psun_image;
	int ret = 0;
	int cntTimeSec = 0;

	psun_ui = find_sun_addr(ID_UI);
	psun_image = find_sun_addr(ID_IMAGE);
	if (!psun_ui || !psun_image)
		return -1;

	unlink(psun_image->sun_path);
		
	sockfd = socket(AF_UNIX, SOCK_DGRAM, 0);
	if (sockfd < 0)
		return -1;

	ret = bind(sockfd, (struct sockaddr *)psun_image, sizeof(*psun_image));
	if (ret < 0)
		return -1;

	while (eventloop_quit == false)
	{
		FD_ZERO(&rset);
		FD_SET(sockfd, &rset);

		timeout.tv_sec = 0;
		timeout.tv_usec = WAIT_TIME * 1000;

		maxfd = sockfd + 1;

		int status = select(maxfd, &rset, NULL, NULL, &timeout);
		if (status < 0)
		{
			print_error("media_cmd_eventloop error %s\n", strerror(errno));
		}
		else if (status == 0)
		{
			continue;
		}
		else
		{
			if (FD_ISSET(sockfd, &rset))
			{
				int ret_len = recvfrom(sockfd, g_PortDataCtrl.recv_buf, MAX_PORT_BUF_LEN, 0, NULL, NULL);
#if 1
				if (ret_len > 0)
				{
					printf("Image socket->Recv: ");
					for (int i = 0; i < ret_len; i++)
						printf("%02x ", g_PortDataCtrl.recv_buf[i]);
					printf("\n");
				}
#endif
				if (ret_len > 0)
				{
					uint8_t *pRxData = NULL;
					uint8_t *pRxOffset = NULL;
					uint8_t *pRet = NULL;

					if (g_PortDataCtrl.rx_len + ret_len >= MAX_PORT_BUF_LEN)
						g_PortDataCtrl.rx_len = 0;

					pRxData = g_PortDataCtrl.rx_data[g_PortDataCtrl.rx_idx];
					pRxOffset = pRxData + g_PortDataCtrl.rx_len;

					memcpy(pRxOffset, g_PortDataCtrl.recv_buf, ret_len);
					g_PortDataCtrl.rx_len += ret_len;

					g_PortDataCtrl.cmd_idx = 0;
					bool bret = CheckFrame(pRxData, g_PortDataCtrl.rx_len, &pRet);
					if (bret)
					{
						for (int i = 0; i < g_PortDataCtrl.cmd_idx; i++)
						{							
							ParseCommFrame(g_PortDataCtrl.cmd_data[i], g_PortDataCtrl.cmd_len[i]);
							usleep(10 * 1000);
						}

						int len = pRet - pRxData;
						int rest = g_PortDataCtrl.rx_len - len;

						g_PortDataCtrl.rx_idx += 1;
						if (g_PortDataCtrl.rx_idx >= MAX_RX_BUF_CNT)
							g_PortDataCtrl.rx_idx = 0;

						memcpy(g_PortDataCtrl.rx_data[g_PortDataCtrl.rx_idx], pRet, rest);
						g_PortDataCtrl.rx_len = rest;
					}
				}
			}			
		}
	}

	close(sockfd);

	return 0;
}





